#include "CheckersBoard.h"
#include <iostream>

CheckersBoard::CheckersBoard()
{
    //ctor
}

CheckersBoard::~CheckersBoard()
{
    //dtor
    int i; //deleting the previous legalmove
    if (legalMoves.size() > 0) {
        for (i=0;i<(int)legalMoves.size();i++)
        {
            delete legalMoves.at(i);
        }
        legalMoves.clear();
    }
}

CheckersBoard::CheckersBoard(const CheckersBoard& other)
{
    //copy ctor
}

CheckersBoard& CheckersBoard::operator=(const CheckersBoard& rhs)
{
    if (this == &rhs) return *this; // handle self assignment
    //assignment operator
    return *this;
}

vector<int> CheckersBoard::getRow(int pRow)
{
    return getBoard().at(pRow);
}

int CheckersBoard::pieceAt(int pRow, int pCol)
{
    return getRow(pRow).at(pCol);
    //return board.at(pRow).at(pCol);
}

void CheckersBoard::initializeBoard()
{
    vector<int> tRow;
    int curRow,curCol;
    //RED
    for (curRow=0; curRow<4; curRow++)
    {
        for(curCol = ((curRow+1) % 2); curCol < BOARD_SIZE; curCol+=2)
        {
            if (curRow % 2 == 0) {
                tRow.push_back(EMPTY);
                tRow.push_back(RED);
            } else {
                tRow.push_back(RED);
                tRow.push_back(EMPTY);
            }
        }
        board.push_back(tRow);
        tRow.clear();
    }

    //EMPTY
    for (curRow=4;curRow<6;curRow++)
    {
        for(curCol=0;curCol<BOARD_SIZE;curCol++)
        {
            tRow.push_back(EMPTY);
        }
        board.push_back(tRow);
        tRow.clear();
    }

    //BLACK
    for (curRow=6; curRow<BOARD_SIZE; curRow++)
    {
        for(curCol = ((curRow+1) % 2); curCol < BOARD_SIZE; curCol+=2)
        {
            if (curRow % 2 == 0) {
                tRow.push_back(EMPTY);
                tRow.push_back(BLACK);
            } else {
                tRow.push_back(BLACK);
                tRow.push_back(EMPTY);
            }
        }
        board.push_back(tRow);
        tRow.clear();
    }
}

bool CheckersBoard::isInside(int pRow, int pCol)
{
    return (pRow >= 0 && pRow < 10 && pCol >= 0 && pCol < 10);
}

bool CheckersBoard::canMove(int player, int pFromRow, int pFromCol, int pToRow, int pToCol)
{
    //fromRow and fromCol are assumed ok
    if (isInside(pFromRow, pFromCol) && isInside(pToRow,pToCol)) {
        if ((pieceAt(pFromRow,pFromCol) == EMPTY) || (pieceAt(pToRow,pToCol) != EMPTY)) {
            return false;
        } else {
            if (player == RED) {
                if (pieceAt(pFromRow,pFromCol) == RED && pToRow < pFromRow) {
                    return false; //gerak ke atas
                } else {
                    return true;
                }
            } else { //BLACK
                if (pieceAt(pFromRow,pFromCol) == BLACK && pToRow > pFromRow) {
                    return false; //gerak ke bawah
                } else {
                    return true;
                }
            }
        }
    } else {
        return false;
    }
}

bool CheckersBoard::canJump(int player, int pFromRow, int pFromCol, int pEnemyRow, int pEnemyCol, int pToRow, int pToCol)
{
    if (isInside(pFromRow, pFromCol) && isInside(pEnemyRow,pEnemyCol) && isInside(pToRow,pToCol)) {
        if (pieceAt(pFromRow,pFromCol) != EMPTY && pieceAt(pEnemyRow,pEnemyCol) != EMPTY && pieceAt(pToRow,pToCol) == EMPTY) {
            if (player == RED) {
                if (pToRow < pFromRow) {
                    //canJumpParameter
                    //std::cout<<"merah loncat ke atas"<<endl;
                    return false;
                }
                if (pieceAt(pFromRow,pFromCol) != RED) {
                    //canJumpParameter
                    //std::cout<<"bukan biji merah"<<endl;
                    return false;
                }
                if (pieceAt(pEnemyRow,pEnemyCol) != BLACK && pieceAt(pEnemyRow,pEnemyCol) != BLACK_KING) {
                    //canJumpParameter
                    //std::cout<<"biji yang diloncatin bukan hitam"<<endl;
                    return false;
                }
                canJumpParameter
                std::cout<<"boleh loncat ;)\n"<<endl;
                return true;
            } else { //BLACK
                if (pToRow > pFromRow) {
                    //canJumpParameter
                    //std::cout<<"hitam loncat ke bawah"<<endl;
                    return false;
                }
                if (pieceAt(pFromRow,pFromCol) != BLACK) {
                    //canJumpParameter
                    //std::cout<<"bukan biji hitam"<<endl;
                    return false;
                }
                if (pieceAt(pEnemyRow,pEnemyCol) != RED && pieceAt(pEnemyRow,pEnemyCol) != RED_KING) {
                    //canJumpParameter
                    //std::cout<<"biji yang diloncatin bukan merah"<<endl;
                    return false;
                }
                //canJumpParameter
                //std::cout<<"boleh loncat ;)"<<endl;
                return true;
            }
        } else {
            //canJumpParameter
            //std::cout<<"biji gak sesuai"<<endl;
            return false;
        }
    } else {
        //canJumpParameter
        //std::cout<<"biji di luar"<<endl;
        return false;
    }
}

void CheckersBoard::calculateLegalMoves(int player)
{
    int i; //deleting the previous legalmove
    if (legalMoves.size() > 0) {
        for (i=0;i<(int)legalMoves.size();i++)
        {
            delete legalMoves.at(i);
        }
        legalMoves.clear();
    }

    int playerKing;
    if (player == RED) {
        playerKing = RED_KING;
    } else {
        playerKing = BLACK_KING;
    }
    int tRow, tCol;
    for (tRow=0;tRow<BOARD_SIZE;tRow++)
    {
        //std::cout << "tRow: " << tRow << endl;
        for (tCol=0;tCol<BOARD_SIZE;tCol++)
        {
            //std::cout << "tCol: "<< tCol << endl;
            if (pieceAt(tRow,tCol) == player || pieceAt(tRow,tCol) == playerKing) {
                //std::cout << "pieceAt: "<< pieceAt(tRow,tCol) << endl;
                if (canJump(player,tRow,tCol,tRow-1,tCol-1,tRow-2,tCol-2)) {
                    legalMoves.push_back( new CheckersMove(tRow,tCol,tRow-2,tCol-2));
                    //std::cout << "lompat atas kiri" << endl;
                }
                if (canJump(player,tRow,tCol,tRow-1,tCol+1,tRow-2,tCol+2)) {
                    legalMoves.push_back( new CheckersMove(tRow,tCol,tRow-2,tCol+2));
                    //std::cout << "lompat atas kanan" << endl;
                }
                if (canJump(player,tRow,tCol,tRow+1,tCol-1,tRow+2,tCol-2)) {
                    legalMoves.push_back( new CheckersMove(tRow,tCol,tRow+2,tCol-2));
                    //std::cout << "lompat bawah kiri" << endl;
                }
                if (canJump(player,tRow,tCol,tRow+1,tCol+1,tRow+2,tCol+2)) {
                    legalMoves.push_back( new CheckersMove(tRow,tCol,tRow+2,tCol+2));
                    //std::cout << "lompat bawah kanan" << endl;
                }

            } else {
                //std::cout << "pieceAt: "<< pieceAt(tRow,tCol) << endl;
            }
        }
    }
    if (legalMoves.size() == 0) {
        for (tRow=0;tRow<BOARD_SIZE;tRow++)
        {
            //std::cout << "tRow: " << tRow << endl;
            for (tCol=0;tCol<BOARD_SIZE;tCol++)
            {
                //std::cout << "tCol: "<< tCol << endl;
                if (pieceAt(tRow,tCol) == player || pieceAt(tRow,tCol) == playerKing) {
                    if (canMove(player,tRow,tCol,tRow-1,tCol-1)) {
                        legalMoves.push_back( new CheckersMove(tRow,tCol,tRow-1,tCol-1));
                        //cout << "gerak atas kiri" << endl;
                    }
                    if (canMove(player,tRow,tCol,tRow-1,tCol+1)) {
                        legalMoves.push_back( new CheckersMove(tRow,tCol,tRow-1,tCol+1));
                        //cout << "gerak atas kanan" << endl;
                    }
                    if (canMove(player,tRow,tCol,tRow+1,tCol-1)) {
                        legalMoves.push_back( new CheckersMove(tRow,tCol,tRow+1,tCol-1));
                        //cout << "gerak bawah kiri" << endl;
                    }
                    if (canMove(player,tRow,tCol,tRow+1,tCol+1)) {
                        legalMoves.push_back( new CheckersMove(tRow,tCol,tRow+1,tCol+1));
                        //cout << "gerak bawah kanan" << endl;
                    }
                } else {
                    //std::cout << "pieceAt: "<< pieceAt(tRow,tCol) << endl;
                }
            }
        }
    }
    //return tMoves;
}

void CheckersBoard::movePiece(CheckersMove* pMove)
{

    int tPiece = pieceAt(pMove->getFromRow(),pMove->getFromCol());
    board.at(pMove->getToRow()).at(pMove->getToCol()) = tPiece;
    board.at(pMove->getFromRow()).at(pMove->getFromCol()) = EMPTY;

    if (pMove->isJump()) {
        int jumpRow = (pMove->getFromRow() + pMove->getToRow()) / 2;
        int jumpCol = (pMove->getFromCol() + pMove->getToCol()) / 2;
        board.at(jumpRow).at(jumpCol) = EMPTY;
    }

    if (pMove->getToRow() == 9 && pieceAt(pMove->getToRow(),pMove->getToCol()) == RED) {
        board.at(pMove->getToRow()).at(pMove->getToCol()) = RED_KING;
    }

    if (pMove->getToRow() == 0 && pieceAt(pMove->getToRow(),pMove->getToCol()) == BLACK) {
        board.at(pMove->getToRow()).at(pMove->getToCol()) = BLACK_KING;
    }

}

void CheckersBoard::calculateLegalJumps(int player, int pRow, int pCol)
{
    int i; //deleting the previous legalmove
    if (legalMoves.size() > 0) {
        for (i=0;i<(int)legalMoves.size();i++)
        {
            delete legalMoves.at(i);
        }
        legalMoves.clear();
    }

    int playerKing;
    if (player == RED) {
        playerKing = RED_KING;
    } else {
        playerKing = BLACK_KING;
    }
    int tRow, tCol;
    for (tRow=0;tRow<BOARD_SIZE;tRow++)
    {
        //std::cout << "tRow: " << tRow << endl;
        for (tCol=0;tCol<BOARD_SIZE;tCol++)
        {
            //std::cout << "tCol: "<< tCol << endl;
            if (pieceAt(tRow,tCol) == player || pieceAt(tRow,tCol) == playerKing) {
                //std::cout << "pieceAt: "<< pieceAt(tRow,tCol) << endl;
                if (canJump(player,tRow,tCol,tRow-1,tCol-1,tRow-2,tCol-2)) {
                    legalMoves.push_back( new CheckersMove(tRow,tCol,tRow-2,tCol-2));
                    //cout << "lompat atas kiri" << endl;
                }
                if (canJump(player,tRow,tCol,tRow-1,tCol+1,tRow-2,tCol+2)) {
                    legalMoves.push_back( new CheckersMove(tRow,tCol,tRow-2,tCol+2));
                    //cout << "lompat atas kanan" << endl;
                }
                if (canJump(player,tRow,tCol,tRow+1,tCol-1,tRow+2,tCol-2)) {
                    legalMoves.push_back( new CheckersMove(tRow,tCol,tRow+2,tCol-2));
                    //cout << "lompat bawah kiri" << endl;
                }
                if (canJump(player,tRow,tCol,tRow+1,tCol+1,tRow+2,tCol+2)) {
                    legalMoves.push_back( new CheckersMove(tRow,tCol,tRow+2,tCol+2));
                    //cout << "lompat bawah kanan" << endl;
                }

            } else {
                //std::cout << "pieceAt: "<< pieceAt(tRow,tCol) << endl;
            }
        }
    }
    //cannot move again beside jumping
}

void CheckersBoard::printBoard()
{
    int tRow,tCol,i;
    cout << "   col|";
    for (i=0;i<BOARD_SIZE;i++)
    {
        cout << i << " ";
    }
    cout << "\n----------------------------\n";
    for (tRow=0;tRow<BOARD_SIZE;tRow++)
    {
        cout << "row: " << tRow << "|";
        for (tCol=0;tCol<BOARD_SIZE;tCol++)
        {
            cout << pieceAt(tRow,tCol) << " ";
        }
        //cout << "\n----------\n";
        cout << "\n";
    }
    cout << "\n";
}

void CheckersBoard::printLegalMoves()
{
    int i;
    for (i=0;i<(int)legalMoves.size();i++)
    {
        /*cout << "fromRow: " << legalMoves.at(i)->getFromRow() << endl;
        cout << "fromCol: " << legalMoves.at(i)->getFromCol() << endl;
        cout << "toRow: " << legalMoves.at(i)->getToRow() << endl;
        cout << "toRow: " << legalMoves.at(i)->getFromRow() << endl;*/
        cout << legalMoves.at(i)->getFromRow() << legalMoves.at(i)->getFromCol() << " " << legalMoves.at(i)->getToRow() << legalMoves.at(i)->getToCol() << endl;
    }
}
